; ======================================================================
; boosta
; Created by Patrick Marum
; Date : 2009/03/19
; Funny and small racing 3d game 
;
; 
;Copyright (c) 2009 <Patrick Marum as patmaba>

;Permission is hereby granted, free of charge, To any person
;obtaining a copy of this software And associated documentation
;files (the "Software"), To deal in the Software without
;restriction, including without limitation the rights To use,
;copy, modify, merge, publish, distribute, sublicense, And/Or sell
;copies of the Software, And To permit persons To whom the
;Software is furnished To do so, subject To the following
;conditions:

;The above copyright notice And this permission notice shall be
;included in all copies Or substantial portions of the Software.

;THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
;EXPRESS Or IMPLIED, INCLUDING BUT Not LIMITED To THE WARRANTIES
;OF MERCHANTABILITY, FITNESS For A PARTICULAR PURPOSE And
;NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS Or COPYRIGHT
;HOLDERS BE LIABLE For ANY CLAIM, DAMAGES Or OTHER LIABILITY,
;WHETHER IN AN ACTION OF CONTRACT, TORT Or OTHERWISE, ARISING
;FROM, OUT OF Or IN CONNECTION WITH THE SOFTWARE Or THE USE Or
;OTHER DEALINGS IN THE SOFTWARE.
; ======================================================================
Include "lib\Inc_Const.bb"
Include "lib\Inc_TChrono.bb"
Include "lib\Inc_Timer.bb"
Include "lib\Inc_TWaypoint.bb"
Include "lib\Inc_TWheel.bb"
Include "lib\Inc_TWall.bb"
Include "lib\Inc_TCar.bb"
Include "lib\Inc_TRaceData.bb"
Include "lib\Inc_Util.bb"
Include "lib\Inc_Vector.bb"
Include "lib\Inc_TList.bb"
Include "lib\Inc_TMap.bb"
Include "lib\Inc_Item.bb"
Include "lib\Inc_Explosion.bb"
Include "lib\Inc_Los.bb"
Include "lib\Inc_Newton.bb"

Const LICENSE_KEY_NEWTON$  = "N0225514)6+6?807'6idm4}4]dM1L1E9"

Type TApplication
	
	Field gameFPS
	Field framePeriod
	Field frameTime
	Field frameElapsed
    Field frameTween#	
	Field frameTicks
	Field frameLimit
	
	
	Field debug
	Field MDL%
	Field TEMPLATE_MISSIL
	Field Cam1%
	Field Light1%
	Field Light2%
	Field Plane1%
    Field Player.TCar
	Field RaceData.TRaceData
	
	Field chrono.TChrono
	
	
	Field Race = False 
	
	Field tm.Timer = Null ; 3sec
	
	Field fntArial50B =0
	Field fntArial15B =0
	
	Field UserCamMode = 5
	Field bWireFrame = False 
	
	Field gMapWayPt.TMap= Null
End Type 

; g_App is the only instance of a TApplication type 
; and the only global variable on this application.
Global g_App.TApplication = Null


; --------------------------------------------------
; Init application
; --------------------------------------------------
App_Init() 

; --------------------------------------------------
; Main loop using tweening 
; --------------------------------------------------
Repeat 
	
	Repeat 
		g_App\frameElapsed = MilliSecs () - g_App\frameTime 
	Until g_App\frameElapsed 
	
	g_App\frameTicks = g_App\frameElapsed / g_App\framePeriod 
	
	g_App\frameTween# = Float (g_App\frameElapsed Mod g_App\framePeriod) / Float (g_App\framePeriod) 
	
	For g_App\frameLimit = 1 To g_App\frameTicks 
		
		If g_App\frameLimit = g_App\frameTicks Then CaptureWorld 
		g_App\frameTime = g_App\frameTime + g_App\framePeriod 
		
		
		; --------------------------------------------------
		; Update application process
		; --------------------------------------------------
    	App_Pre_Update() 
		UpdateWorld ; update collision system
		App_Post_Update()
	Next 
	
	RenderWorld g_App\frameTween 
	
	; --------------------------------------------------
	; Display 2d application 
	; --------------------------------------------------	
	App_Update2D()
	Flip() 
	
Until KeyDown(1) 

; --------------------------------------------------
;Clear all resources and end application
; --------------------------------------------------
App_Release()
End() 


; --------------------------------------------------
; App_Release
; Clear all ressources used by application
; --------------------------------------------------
Function App_Release() 
	FreeFont g_App\fntArial15B
	FreeFont g_App\fntArial50B
	
	TWall_DeleteAll()
	TCAR_DeleteAll()
	
	phWorldDestroy()
	ClearWorld  True, True, True
	EndGraphics() 
End Function 
End() 



; --------------------------------------------------
; App_Init
; Init 3d world and rendering settings
; --------------------------------------------------
Function App_Init()  
	Graphics3D 800/3,600/3,16,2  	
;	Graphics3D 800,600,16,2  	
;	Graphics3D 1024,800,16,2  		
	
	SetBuffer BackBuffer() 
	SeedRnd MilliSecs() 	
	
	
	; You must have only one instance of Tapplication
	Delete Each TApplication
	g_App = New TApplication
	g_App\gameFPS = 50
	g_App\framePeriod=0
	g_App\frameTime=0
	
	g_App\Player.TCar=	Null   
	g_App\RaceData.TRaceData = Null
	g_App\UserCamMode = 5
	g_App\debug      = 	False
	g_App\MDL%		=	0 
	g_App\Cam1%		=	0  
	g_App\Light1%	=	0  
	g_App\Light2%	=	0  
	g_App\Plane1%	=	0  
	g_App\chrono.TChrono = Null 
	g_App\Race = False 
	g_App\fntArial50B = LoadFont("Arial",50,True,False,False) 
	g_App\fntArial15B = LoadFont("Arial",15,True,False,False)  
	
	WireFrame 0
	g_App\Cam1	=	CreateCamera	() 
	PositionEntity  g_App\Cam1,230,100,10
	CameraRange g_App\Cam1,.1,1000 
	CameraClsColor g_App\Cam1,0,0,0 
	
	
	g_App\Light1=CreateLight()
	MoveEntity g_App\Light1,0,200,0
	RotateEntity g_App\Light1,30,30,30
	
	g_App\Light2=CreateLight()
	MoveEntity g_App\Light2,100,100,0
	RotateEntity g_App\Light2,230,30,30
	
    ; Initialize physics
	phWorldCreate(True,LICENSE_KEY_NEWTON$) ; if parameter is set to True, a horizontal plane at (0,0,0) will be created
	phWorldSetGravity(0,-40,0)
	
	
	
	g_App\Plane1=	CreatePlane		() 
	
	EntityColor(g_App\Plane1,80,200,255) 
	NameEntity(g_App\Plane1,"SOL"+1) 
	PositionEntity g_App\Plane1,0,-0.01,0
	
	
	g_App\TEMPLATE_MISSIL= TItem_Template_Missil( "model/missile1.3ds" ) 
	g_App\MDL =	TCar_MeshTemplate() 
	
	
	g_App\framePeriod = 1000 / g_App\gameFPS 
	g_App\frameTime = MilliSecs () - g_App\framePeriod 	
	
    ; init countdown timer
    ; when player start race for the 3 first second
	g_App\tm = SetTimer(3000)
	
	
	App_CreateCircuit()   
	
    App_CreateCar( "IA1",Rand(30,50))
    App_CreateCar( "IA2",Rand(30,50))
    App_CreateCar( "IA3",Rand(30,50))
    App_CreateCar( "IA4",Rand(30,50))
	
    App_CreateCar( "IA5",Rand(30,50))
    App_CreateCar( "IA6",Rand(30,50))
    App_CreateCar( "IA7",Rand(30,50))
	g_App\Player = App_CreateCar( "Me", 25, True )
	
	TCar_SetPositionXZByWaypoint("IA1",26,0,0)
	TCar_SetPositionXZByWaypoint("IA2",25,0,0)
	TCar_SetPositionXZByWaypoint("IA3",24,0,0)
	TCar_SetPositionXZByWaypoint("IA4",23,0,0)
	TCar_SetPositionXZByWaypoint("IA5",22,0,0)
	TCar_SetPositionXZByWaypoint("IA6",21,0,0)
	TCar_SetPositionXZByWaypoint("IA7",20,0,0)
	TCar_SetPositionXZByWaypoint("Me",15,3,0)
	
	g_App\bWireFrame = False
End Function 



Function App_CreateCar.TCar( p_sName$, p_fSpeed#=20, p_bIsHuman=False)  
	
	Local l_c.TCar = Null 
	
	l_c = TCar_CreateVoiture(p_bIsHuman) 	
	TCar_SetName( l_c, p_sName$ )
	TCar_SetSpeed(p_sName$,p_fSpeed#)
	If 	p_bIsHuman Then 
		TCar_SetColor( p_sName$, 80,80,255 )
	Else
		TCar_SetColor( p_sName$, 255,80,80 )
    End If
	
	Return l_c
End Function 


Function App_CreateCircuit() 
	
	Local lz#,lx#,mi_ts#   = (kTILE_SIZE/2.0)     
	Local w.TWall = Null
	Local tilenum$=""
	Local t, x_Floor, z_Floor
	
	
	g_App\RaceData=TRaceData_Create("race01")
	
	; Print them all! 
	For lz# = 0 To (g_App\RaceData\nb_row-1)
		For lx# = 0 To (g_App\RaceData\nb_col-1)
			
			; get value from tile data stored into file circuit.txt
			tilenum$ = TRaceData_GetTile$( g_App\RaceData, (g_App\RaceData\nb_row-1)-lz, lx )			
			
			If tilenum$ <> "0"
				t=UTIL_CreateFloor("tile"+tilenum$+".png", -mi_ts,mi_ts,-mi_ts,mi_ts)			
				
				x_Floor = (lx*(kTILE_SIZE));+lx
				z_Floor = (lz*(kTILE_SIZE));+lz
				PositionEntity t,x_Floor,0.05,z_Floor
				
				If tilenum$ = "1" ; =
					TWall_Create( t, True, False, True, False)
				End If
				
				If tilenum$ = "2"  ; ||
					TWall_Create( t, False, True, False, True)
				EndIf 
				
				If tilenum$ = "3"  ; L
					TWall_Create( t, False, False, True, True)
				EndIf 
				
				If tilenum$ = "4"  ; |-
					TWall_Create( t, True, False, False, True)
				EndIf 
				
				If tilenum$ = "5"  ; -|
					TWall_Create( t, True, True, False, False)
				EndIf 
				
				If tilenum$ = "6"  ; _|
					TWall_Create( t, False, True, True, False)
				EndIf 
				
			EndIf 
		Next 
	Next 
	
	App_CreateWayPoint()
End Function 



Function App_CreateWayPoint()
    Local lx#,lz#
	Local wp,x_Floor,z_Floor
	For lz# = 0 To (g_App\RaceData\nb_row-1)
		For lx# = 0 To (g_App\RaceData\nb_col-1)
			
			; get value from tile data stored into file circuit.txt
			wp = TRaceData_GetWp( g_App\RaceData, (g_App\RaceData\nb_row-1)-lz, lx )			
			If wp > 0
				x_Floor = (lx*(kTILE_SIZE));+lx
				z_Floor = (lz*(kTILE_SIZE));+lz
				TWayPoint_CreateWayPoint( wp, x_Floor,1,z_Floor )
			EndIf 
		Next 
	Next 
	
	TWayPoint_PointByOrder() ; point direction prev wp to next wp
	
	
End Function



Function App_Pre_Update() 
	
	
	If KeyHit(17) Then  g_App\bWireFrame = Not g_App\bWireFrame
	WireFrame g_App\bWireFrame
	
	If g_App\Race = True  
		TCar_Update() 
		Car_Position()
		TExplosion_Update()
	End If 
	
	phWorldStep(0.01)
End Function 



Function App_Post_Update() 
	If g_App\Race 
		TItem_Update()
		For c.TCar = Each TCar
			TCar_SetMeshByBody( c )
		Next 
	EndIf 
End Function 



Function App_Update2D()
	
	Color 255,255,255	
	Local l_c.TCar = Null 
	
	If g_App\Race = False	
		; Start Race countdown
		SetFont g_App\fntArial50B
		Color 250,0,0
		
		If	TimeOut(g_App\tm) = False 
			time_val = g_App\tm\timeOut-MilliSecs()
			If time_val < 1000
				Text GraphicsWidth()/2,GraphicsHeight()/2, "one",True,True
			ElseIf time_val > 1000 And time_val < 2000 
				Text GraphicsWidth()/2,GraphicsHeight()/2, "two",True,True
			ElseIf time_val > 2000
				Text GraphicsWidth()/2,GraphicsHeight()/2, "three",True,True
			EndIf 
		Else 
			g_App\Race = True
			g_App\chrono = TChrono_Create()	
			TChrono_StartStop(g_App\chrono)				   	
		End If
		
	Else 
		SetFont g_App\fntArial15B
		Color 250,255,0
		If g_App\debug = True 
			TWayPoint_Text(g_App\Cam1)
			
			For l_c.TCar = Each TCar
				If EntityInView(l_c\mesh,g_App\Cam1)
					CameraProject(g_App\Cam1,EntityX(l_c\mesh),EntityY(l_c\mesh),EntityZ(l_c\mesh)) 
					Text ProjectedX#(),ProjectedY#(), EntityName(l_c\mesh)+"  Lap "+l_c\nb_loop+", Pos="+l_c\Race_pos
				EndIf
			Next 
			
		EndIf
		
		; display position lap
;		Local t$[30]	
;		Text 10,10 , "Position and Lap"
;		Color 255,0,0
;		For l_c.TCar = Each TCar		
;			t[l_c\Race_pos] = "  Lap "+l_c\nb_loop + "   -   " + EntityName(l_c\mesh)
;		Next 
;		Local i=0,l=0
;		For i=1 To TCar_count()-1
;			If Instr(t[i], g_App\Player\name) 
;				Color 255,255,255
;			Else 	
;				Color 255,30,30
;			EndIf 
;			
;			Text 1,l+30, i + ". " +t[i]
;			l=l+12
;		Next 
		
		If g_App\Player\bMissil = True Then
			Color 105,105,105
			Rect GraphicsWidth()-200,0,200,40
			Color 0,255,255
			Text GraphicsWidth()-200,10 , "Missilie Loaded(Fire=CTRL Left)"
		EndIf 
		
		Color 255,255,255
		Text 10,GraphicsHeight()-40, "Camera View( presse Tab )"
	EndIf 
	
End Function 



Function Car_Position()
    Local tmp=0
    Local tmpn$=""
 	Local l_car[50]
 	Local l_car_pos[50]
 	Local l_car_name$[50]
	
	; for each_car calculate Race_pos_factor = loop done + nearest way point
	Local j=0,i=0
	Local l_c.TCar
	For l_c.TCar = Each TCar 
		l_c\Race_pos_factor = (l_c\nb_loop * TWayPoint_Count() )+ l_c\wayp\order_sequence
		l_car[i] = l_c\mesh
		l_car_pos[i] = l_c\Race_pos_factor
		l_car_name[i] = l_c\name$
		l_c\Race_pos = 0
		i=i+1
	Next 
	
	For i=0 To TCar_Count()-1
		For j=0 To TCar_Count()-1 
			If i<>j Then 
				If l_car_pos[i] >  l_car_pos[j]
					tmp=l_car_pos[i]
					l_car_pos[i] = l_car_pos[j]
					l_car_pos[j] = tmp 
					
					tmp=l_car[i]
					l_car[i] = l_car[j]
					l_car[j] = tmp 				
					
					tmpn$ = l_car_name[i]
					l_car_name[i] = l_car_name[j]
					l_car_name[j] = tmpn$
				End If
			EndIf
		Next
	Next 
	
	For i=0 To TCar_Count()-1
		l_c = TCar_GetByName( l_car_name[i] )
		If l_c <> Null 
			l_c\Race_pos_factor=l_car_pos[i]
			l_c\Race_pos = i
		Else 
			Stop 
		End If
	Next 	
	
	
End Function



; Structure who store all info about a spherical Line






;~IDEal Editor Parameters:
;~C#Blitz3D